# -*- coding: utf-8 -*-
"""
StarRocks集群对比报表 Provider。
"""
from __future__ import annotations

import json
from datetime import datetime, timedelta
from typing import Any, Dict, List, Optional, Tuple

from app.blueprints.reports.providers.base import BaseProvider, SafeDict
from app.services.report_service import ReportTemplateService
from app.utils.logger import FlinkLogger

logger = None


def get_logger():
    global logger
    if logger is None:
        logger = FlinkLogger.get_logger(__name__)
    return logger


class ClusterComparisonProvider(BaseProvider):
    """StarRocks集群对比报表数据提供者"""

    def _get_sql_template(self) -> str:
        """从数据库 default_params 读取 SQL 模板"""
        if not self.template_code:
            raise ValueError("模板编码不能为空")
        
        try:
            tpl = ReportTemplateService.get_template_by_code(self.template_code)
            if not tpl:
                raise ValueError(f"模板 {self.template_code} 不存在")
            
            default_params = tpl.get("default_params")
            if isinstance(default_params, str):
                default_params = json.loads(default_params)
            
            sql_template = default_params.get("sql_template", "")
            if not sql_template:
                raise ValueError("模板配置中缺少 sql_template")
            
            return sql_template
        except Exception as e:
            get_logger().error(f"读取 SQL 模板失败: {e}", exc_info=True)
            raise

    def _get_field_labels(self) -> Dict[str, str]:
        """从数据库读取字段标签"""
        default_labels = {
            "table_name": "表名",
            "source_rows": "源集群行数",
            "source_size": "源集群数据大小(字节)",
            "target_rows": "目标集群行数",
            "target_size": "目标集群数据大小(字节)",
            "row_diff": "行数差值",
            "size_diff": "数据大小差值(字节)",
            "diff_rate": "差异率"
        }
        
        if self.template_code:
            try:
                tpl = ReportTemplateService.get_template_by_code(self.template_code)
                if tpl:
                    default_params = tpl.get("default_params")
                    if isinstance(default_params, str):
                        default_params = json.loads(default_params)
                    template_labels = default_params.get("field_labels", {})
                    if template_labels:
                        default_labels.update(template_labels)
            except Exception:
                pass
        
        return default_labels

    def _build_table_filter(self, table_selection: Dict[str, Any]) -> str:
        """构建表过滤条件"""
        selection_type = table_selection.get("selection_type", "specific_tables")
        
        if selection_type == "all_in_database":
            # 全库表，不添加额外过滤
            return ""
        elif selection_type == "specific_tables":
            table_names = table_selection.get("table_names", [])
            if table_names:
                tables_str = "', '".join(table_names)
                return f" AND TABLE_NAME IN ('{tables_str}')"
        
        return ""

    def collect(self) -> Dict[str, Any]:
        """收集数据"""
        try:
            get_logger().info("[集群对比] 开始收集数据")
            
            # 获取数据源配置
            source_config = self.params.get("source_cluster_config", {})
            target_config = self.params.get("target_cluster_config", {})
            source_ds_id = source_config.get("data_source_id")
            target_ds_id = target_config.get("data_source_id")
            
            if not source_ds_id or not target_ds_id:
                raise ValueError("源集群和目标集群数据源ID不能为空")
            
            # 获取表选择配置
            table_selection = self.params.get("table_selection", {})
            database_name = table_selection.get("database_name")
            if not database_name:
                raise ValueError("数据库名不能为空")
            
            # 构建表过滤条件
            table_filter = self._build_table_filter(table_selection)
            
            # 获取字段标签
            field_labels = self._get_field_labels()
            
            # 从源集群查询
            source_query = f"""
                SELECT 
                    TABLE_NAME as table_name,
                    TABLE_ROWS as row_count,
                    DATA_LENGTH as data_size
                FROM information_schema.TABLES
                WHERE TABLE_SCHEMA = '{database_name}'{table_filter}
            """
            
            with self.get_data_source_connection(source_ds_id) as conn:
                cursor = conn.cursor()
                cursor.execute(source_query)
                source_results = {row[0]: (row[1] or 0, row[2] or 0) for row in cursor.fetchall()}
            
            # 从目标集群查询
            with self.get_data_source_connection(target_ds_id) as conn:
                cursor = conn.cursor()
                cursor.execute(source_query)  # 使用相同的查询
                target_results = {row[0]: (row[1] or 0, row[2] or 0) for row in cursor.fetchall()}
            
            # 合并结果
            all_tables = set(source_results.keys()) | set(target_results.keys())
            
            columns = [
                field_labels.get("table_name", "表名"),
                field_labels.get("source_rows", "源集群行数"),
                field_labels.get("source_size", "源集群数据大小(字节)"),
                field_labels.get("target_rows", "目标集群行数"),
                field_labels.get("target_size", "目标集群数据大小(字节)"),
                field_labels.get("row_diff", "行数差值"),
                field_labels.get("size_diff", "数据大小差值(字节)"),
                field_labels.get("diff_rate", "差异率")
            ]
            
            rows = []
            for table_name in sorted(all_tables):
                source_rows, source_size = source_results.get(table_name, (0, 0))
                target_rows, target_size = target_results.get(table_name, (0, 0))
                row_diff = target_rows - source_rows
                size_diff = target_size - source_size
                diff_rate = f"{round((row_diff * 100.0 / source_rows) if source_rows > 0 else 0, 2)}%"
                
                rows.append([
                    table_name,
                    source_rows,
                    source_size,
                    target_rows,
                    target_size,
                    row_diff,
                    size_diff,
                    diff_rate
                ])
            
            get_logger().info(f"[集群对比] 查询完成，返回 {len(rows)} 条记录")
            
            # 根据 display_fields 过滤
            filtered_columns, filtered_rows = self._filter_display_fields(columns, rows)
            if filtered_columns is not None:
                columns = filtered_columns
                rows = filtered_rows
            
            return {
                "query_result": {
                    "columns": columns,
                    "rows": rows
                }
            }
            
        except Exception as exc:
            get_logger().error(f"[集群对比] 收集数据失败: {exc}", exc_info=True)
            raise

    def _filter_display_fields(
        self, columns: List[str], rows: List[List[Any]]
    ) -> Tuple[Optional[List[str]], Optional[List[List[Any]]]]:
        """根据 display_fields 过滤列"""
        display_fields = self.params.get("display_fields")
        if not display_fields:
            return None, None
        
        field_labels = self._get_field_labels()
        column_index_map = {col: idx for idx, col in enumerate(columns)}
        
        filtered_columns = []
        selected_indexes = []
        
        for field in display_fields:
            label = field_labels.get(field)
            if not label:
                continue
            column_idx = column_index_map.get(label)
            if column_idx is None:
                continue
            filtered_columns.append(label)
            selected_indexes.append(column_idx)
        
        if not filtered_columns:
            return [], []
        
        filtered_rows = [
            [row[idx] if idx < len(row) else None for idx in selected_indexes]
            for row in rows
        ]
        
        return filtered_columns, filtered_rows

    def validate_params(self) -> List[str]:
        """验证参数"""
        errors = []
        
        source_config = self.params.get("source_cluster_config")
        if not source_config:
            errors.append("缺少源集群配置")
        elif not source_config.get("data_source_id"):
            errors.append("源集群数据源ID不能为空")
        
        target_config = self.params.get("target_cluster_config")
        if not target_config:
            errors.append("缺少目标集群配置")
        elif not target_config.get("data_source_id"):
            errors.append("目标集群数据源ID不能为空")
        
        table_selection = self.params.get("table_selection")
        if not table_selection:
            errors.append("缺少表选择配置")
        elif not table_selection.get("database_name"):
            errors.append("数据库名不能为空")
        
        return errors

    def preview_sql(self) -> str:
        """生成预览SQL"""
        return "-- 此报表需要从两个数据源分别查询，无法生成单一SQL预览"
